from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional, List
from module_user.dao.bg_user_affiliate_dao import BgUserAffiliateDao
from module_user.dao.bg_affiliate_relation_dao import BgAffiliateRelationDao
from module_user.dao.bg_affiliate_commission_dao import BgAffiliateCommissionDao
from module_user.entity.vo.bg_user_affiliate_vo import BgUserAffiliateModel, AffiliateStatsModel, InviteeInfoModel
from decimal import Decimal

from utils.string_util import StringUtil


class BgUserAffiliateService:
    """用户推广服务"""

    def __init__(self):
        self.affiliate_dao = BgUserAffiliateDao()
        self.relation_dao = BgAffiliateRelationDao()
        self.commission_dao = BgAffiliateCommissionDao()

    async def get_or_create_affiliate_info(self, db: AsyncSession, user_id: int) -> BgUserAffiliateModel:
        """获取或创建用户推广信息"""
        # 先查询是否已存在
        affiliate_info = await self.affiliate_dao.get_by_user_id(db, user_id)
        
        if not affiliate_info:
            # 生成推广码
            affiliate_code = await self._generate_affiliate_code(db)
            
            # 创建推广信息
            affiliate_info = await self.affiliate_dao.create_affiliate_info(
                db, user_id, affiliate_code, Decimal('5.00')
            )
        
        return BgUserAffiliateModel.from_orm(affiliate_info)

    async def get_affiliate_info(self, db: AsyncSession, user_id: int) -> Optional[BgUserAffiliateModel]:
        """获取用户推广信息"""
        affiliate_info = await self.affiliate_dao.get_by_user_id(db, user_id)
        if affiliate_info:
            return BgUserAffiliateModel.from_orm(affiliate_info)
        return None

    async def get_affiliate_stats(self, db: AsyncSession, user_id: int) -> AffiliateStatsModel:
        """获取推广统计信息"""
        stats = await self.affiliate_dao.get_affiliate_stats(db, user_id)
        return AffiliateStatsModel(**stats)

    async def get_invitee_list(self, db: AsyncSession, user_id: int, page: int = 1, size: int = 20) -> List[InviteeInfoModel]:
        """获取被邀请人列表"""
        invitee_list = await self.affiliate_dao.get_invitee_list(db, user_id, page, size)
        return [InviteeInfoModel(**item) for item in invitee_list]

    async def get_commission_records(self, db: AsyncSession, user_id: int, page: int = 1, size: int = 20) -> List[dict]:
        """获取返利记录列表"""
        return await self.affiliate_dao.get_commission_records(db, user_id, page, size)

    async def process_user_registration(self, db: AsyncSession, user_id: int, affiliate_code: str = None):
        """处理用户注册时的推广关系"""
        if not affiliate_code:
            return
            
        # 查找推广者
        inviter_info = await self.affiliate_dao.get_by_affiliate_code(db, affiliate_code)
        if not inviter_info:
            return
            
        # 检查是否已存在推广关系
        if await self.relation_dao.is_invitee_exists(db, user_id):
            return
            
        # 创建推广关系
        await self.relation_dao.create_relation(
            db, inviter_info.user_id, user_id, affiliate_code
        )

    async def process_order_commission(self, db: AsyncSession, order_id: int, user_id: int, order_amount: Decimal, auto_commit = True):
        """处理订单返利"""
        # 查找用户的推广关系
        relation = await self.relation_dao.get_by_invitee_id(db, user_id)
        if not relation:
            return
            
        # 获取推广者信息
        inviter_info = await self.affiliate_dao.get_by_user_id(db, relation.inviter_id)
        if not inviter_info:
            return
            
        # 创建返利记录
        commission_record = await self.commission_dao.create_commission_record(
            db, relation.inviter_id, user_id, order_id, 
            order_amount, inviter_info.commission_rate, auto_commit = auto_commit,
        )
        
        # 更新推广者累计返利
        await self.affiliate_dao.update_total_commission(
            db, relation.inviter_id, commission_record.commission_amount, auto_commit=auto_commit
        )
        
        return commission_record

    async def _generate_affiliate_code(self, db: AsyncSession) -> str:
        """生成推广码"""
        while True:
            # 生成8位随机码
            code = StringUtil.gen_short_id()
            
            # 检查是否已存在
            if not await self.affiliate_dao.get_by_affiliate_code(db, code):
                return code

    # 管理端方法
    async def get_admin_affiliate_list(self, db: AsyncSession, page: int, size: int, 
                                     email: str = None, affiliate_code: str = None, 
                                     status: int = None) -> dict:
        """获取推广返利列表（管理端）"""
        return await self.affiliate_dao.get_admin_affiliate_list(
            db, page, size, email, affiliate_code, status
        )

    async def update_affiliate_status(self, db: AsyncSession, user_id: int, status: int):
        """更新推广状态"""
        return await self.affiliate_dao.update_affiliate_status(db, user_id, status)

    async def settle_commission(self, db: AsyncSession, commission_id: int):
        """结算返利"""
        # 调用DAO层的结算方法
        await self.commission_dao.settle_commission(db, commission_id)
        return {"success": True}

    async def cancel_commission(self, db: AsyncSession, commission_id: int):
        """取消返利"""
        # 调用DAO层的取消方法
        await self.commission_dao.cancel_commission(db, commission_id)
        return {"success": True}

    async def batch_settle_commission(self, db: AsyncSession, user_id: int):
        """批量结算返利"""
        # 获取用户的所有待结算返利记录ID
        pending_commission_ids = await self.affiliate_dao.get_pending_commissions_by_user(db, user_id)
        
        settled_count = 0
        for commission_id in pending_commission_ids:
            try:
                await self.commission_dao.settle_commission(db, commission_id)
                settled_count += 1
            except Exception as e:
                print(f"结算返利记录 {commission_id} 失败: {e}")
                continue
        
        return {"success": True, "settled_count": settled_count}

    async def update_ali_pay_info(self, db: AsyncSession, user_id: int, ali_pay_account: str = None, ali_pay_name: str = None):
        """更新支付宝信息"""
        return await self.affiliate_dao.update_ali_pay_info(db, user_id, ali_pay_account, ali_pay_name)
